﻿/**
  *FileName:    ztest
  *Date:        23/3/26 周日 下午 1:31:11
  *Author:      Zhou Hang
  *Version:     1.0
  *Description: 测试函数聚居地
*/
#pragma once
#include "mline.h"
#include "mcircle.h"
#include "fill.h"
#include "cut.h"
#include "curve.h"
#include "zeigen.h"
#include "zdebug.h"
using namespace std;


/* vector<POINT> 转 POINT[] 
 * 因为easyx需要POINT[], 有时候需要二者转换
 * (废弃)
 */
void vec2arr(vector<POINT> points, POINT new_points[]) {
	int n = points.size();
	for (int i = 0; i < n; i++) {
		new_points[i] = points[i];
	}
}

// 综合的直线测试,需要依赖mline.h中的line_test函数
void LineTest()
{
	initgraph(THEIGHT, TWIDTH);

	line_test(normal_line, "斜率直线算法");
	line_test(dda_line, "数值微分直线算法");
	//line_test(mp_line, "中点直线算法");
	line_test(bresenham_line, "Bresenham直线算法");

	saveimage(_T(".\\a.bmp"));
	int key = _getch();
	closegraph();
}

// 综合的圆形测试,需要依赖mcircle.h中的circle_test函数
void CircleTest()
{
	initgraph(THEIGHT, TWIDTH);
	//circle_test(mp_circle, "中点画圆算法");
	//circle_test(bresenham_cicle, "bresenham画圆算法");
	circle_test(pnm_circle, "正负法画圆算法");
	//saveimage(_T("./img/circle_test.bmp"));
	int key = _getch();
	closegraph();
}

// 一个具有简单坐标轴的环境
void createEnv() {
	initgraph(700, 700);
	setorigin(300, 300);
	setbkcolor(WHITE);
	cleardevice();
	// 将坐标轴打印出来，方便调试
	setfillcolor(BLACK);
	fillcircle(0, 0, 4);
	setcolor(GREEN);
	line(-400, 0, 400, 0);
	line(0, -400, 0, 400);
}

// 填充算法测试，包含两个测试用例
void FillTest() {
	createEnv();

	vector<POINT> p = {
		{50, 200},
		{200, 200},
		{200, 50},
		{50, 50},
		{40, 150}
	};
	vector<POINT> p2 = {
		{50, 100}, {-150, 300}, {-250, 50},
		{-150, -250}, {0, -50}, {100, -250},
		{300, 150}
	};

	m_polygon(p2, RED);

	Fill f(p2, 7);
	//cout << f.repr() << endl;
	f.show();
	f.fill(RED);

	int key = _getch();
	closegraph();
}

// 直线剪裁算法测试
void CutTest1() {
	initgraph(600, 700);
	setbkcolor(WHITE);
	cleardevice();
	// 裁切框, 只支持矩形裁剪框
	int xl = 100, yb = 50, xr = 400, yt = 600;
	Cut cut(xl, yb, xr, yt);
	cut.drawRect();

	// inside
	cut.lineCut({ 10, 200 }, { 300, 90 });  // LEFT to inside
	cut.lineCut({ 10, 10 }, { 300, 90 });  // LB to inside
	cut.lineCut({ 200, 10 }, { 300, 90 });  // BOTTOM to inside
	cut.lineCut({ 10, 100 }, { 550, 300 });  // LEFT to inside to RIGHT
	cut.lineCut({ 10, 10 }, { 550, 650 });  // LB to inside to RT
	cut.lineCut({ 200, 300 }, { 300, 300 });  // inside

	// outside
	cut.lineCut({ 200, 25 }, { 300, 10 });  // BOTTOM outside
	cut.lineCut({ 200, 625 }, { 300, 610 });  // TOP outside
	cut.lineCut({ 50, 60 }, { 60, 500 });  // LEFT outside
	cut.lineCut({ 500, 100 }, { 550, 550 });  // RIGHT outside

	int key = _getch();
	closegraph();
}

// 多边形裁切算法测试
void CutTest2() {
	initgraph(600, 700);
	setbkcolor(WHITE);
	cleardevice();

	// 裁切框, 只支持矩形裁剪框
	int xl = 100, yb = 50, xr = 400, yt = 600;
	Cut cut(xl, yb, xr, yt);
	cut.drawRect();

	vector<POINT> p1 = {
		{150, 20}, {50, 200}, {200, 300}, {300, 100}
	};
	vector<POINT> p2 = {
		{150, 20}, {50, 200}, {200, 300}, {420, 250},  {300, 100}
	};
	cut.polyCut(p1, 4);
	vector<POINT> new_poly = cut.polyCut(p2, 5);

	// 对新裁剪得到的多边形进行填充
	Fill f(new_poly, new_poly.size());
	f.fill(RED);

	int key = _getch();
	closegraph();
}

// 测试easyx自带的曲线绘制（来自官网例程 https://docs.easyx.cn/zh-cn/polybezier）
void EasyXCurveDemo()
{
	initgraph(400, 400);
	setbkcolor(WHITE);
	cleardevice();
	setcolor(BLACK);

	POINT pts[] = { {150, 200}, {160, 150}, {240, 150}, {250, 100}, {260, 150}, {340, 150}, {350, 200} };
	setlinecolor(DARKGRAY);
	polyline(pts, 7);		// 画灰色的辅助线
	setlinecolor(GREEN);
	polybezier(pts, 7);		// 画绿色的贝塞尔曲线
	int key = _getch();
	closegraph();
}

// 测试自己的曲线绘制方法
void CurveTest() {
	initgraph(400, 400);
	setbkcolor(WHITE);
	cleardevice();

	vector<POINT> p1 = {
		{150, 200}, {160, 150}, {240, 150},
		{250, 100}, {260, 150}, {340, 150},
		{350, 200}
	};

	vector<POINT> p2 = {
		{50, 50}, {60, 100}, {100, 70}
	};
	vector<POINT> p3 = {
		{50, 100}, {150, 20}, {300, 300}, {350, 200}
	};
	vector<POINT> p4 = {
		{50, 100}, {150, 20}, {200, 300}, {350, 200}, {380, 250}
	};
	vector<POINT> inf = {
		{50, 100}, {100, 50}, {200, 150}, {250, 100}, {200, 50}, {100, 150}
	};

	Curve c;

	c.draw3PParabola(p2, GREEN);
	c.drawDataPoints(RED);
	//c.draw4PParabola(p3, RED);
	//c.drawParabola(p4, BLUE);
	//c.drawParabola_Bad(p3, GREEN);  //会得到一个不连接的曲线
	
	//c.draw2Bezier(p3, RED);
	//c.draw3Bezier(p3, GREEN);

	//c.draw2BSpline(p3, BLUE);
	//c.draw3BSpline(p3, BLACK);

	int key = _getch();
	closegraph();
}

// 可以填充的封闭曲线
void CurveTest2()
{
	initgraph(400, 400);
	setbkcolor(WHITE);
	cleardevice();

	vector<POINT> p = {
		{50, 50}, {100, 120}, {200, 300}, {250, 130}
	};

	Curve c;
	c.drawParabola(p, BLACK, true);
	//c.draw4PParabola(p, BLACK);
	setfillcolor(YELLOW);
	floodfill(90, 90, BLACK);

	int key = _getch();
	closegraph();
}

// ZEigen 测试用例1
void ZEigenTest1() {
	// TODO: c++的cout能不能有简单的方式修改终端颜色呢?
	cout << ASNI_FG_BLUE << "=========测试ZEigen基本用法=========" << ASNI_NONE << endl << endl;

	ZEigen::VectorXf v1(vector<float>{ 1.2, 2.3 });
	cout << "使用" << ASNI_FG_YELLOW << "vector<float>{ 1.2, 2.3 })" << ASNI_NONE 
		<< "构造VectorXf：" << ASNI_FG_GREEN << v1 << ASNI_NONE << endl;
	ZEigen::VectorXf v2(POINT{ 520, 400 });
	cout << "使用" << ASNI_FG_YELLOW << "POINT{520, 400}" << ASNI_NONE
		<< "构造VectorXf：" << ASNI_FG_GREEN << v2 << ASNI_NONE << endl;

	ZEigen::MatrixXf mat1({ {1.2, 2.3}, {5.6, 5.7} });
	cout << "MatrixXf的构造函数和输出形式:" << endl;
	cout << ASNI_FG_GREEN << mat1 << ASNI_NONE << endl;

	ZEigen::MatrixXf mat2({ { 1,2 }, { 3,4 } });
	// ZEigen::MatrixXf mv({ {5}, {6} });
	ZEigen::VectorXf mv(vector<float>{ 5, 6 });
	ZEigen::MatrixXf ret = mat2 * mv;  // 
	cout << "支持矩阵乘以向量:" << endl;
	cout << mat2 << " * " << mv << "=" << endl << ret << endl;
}

// ZEigen 测试用例2
void ZEigenTest2() {
	cout << ASNI_FG_BLUE << "=========测试变换矩阵相关函数=========" << ASNI_NONE << endl << endl;

	ZEigen::MatrixXf trans_rotate = ZEigen::ComposingTransform({ ZEigen::Translation3f(3, 3), ZEigen::Rotate3f() });
	cout << "先平移再旋转" << endl << trans_rotate << endl;
	ZEigen::MatrixXf rotate_trans = ZEigen::ComposingTransform({ ZEigen::Rotate3f(), ZEigen::Translation3f(3, 3) });
	cout << "先旋转再平移" << endl << rotate_trans << endl;

	POINT to_transform_point{ 1,2 };
	POINT res = ZEigen::TransformPoint(ZEigen::Translation3f(3, 3), to_transform_point);
	POINT res2 = ZEigen::TransformPoint(ZEigen::Rotate3f(), res);
	POINT res3 = ZEigen::TransformPoint({ ZEigen::Translation3f(3, 3), ZEigen::Rotate3f() }, to_transform_point);
	POINT res4 = ZEigen::TransformPoint({ ZEigen::Rotate3f(), ZEigen::Translation3f(3, 3) }, to_transform_point);
	cout << ASNI_FG_YELLOW << "对点(" << to_transform_point.x << ", " << to_transform_point.y << ")做如下变换:" << ASNI_NONE << endl;
	cout << "平移( 3,3 )后得到坐标:   (" << res.x << ", " << res.y << ")" << endl;
	cout << "再逆时针旋转45度后得坐标: (" << res2.x << ", " << res2.y << ")" << endl;
	cout << "先平移( 3,3 )后旋转45度: (" << res3.x << ", " << res3.y << ")" << endl;
	cout << "先旋转45度后平移( 3,3 ): (" << res4.x << ", " << res4.y << ")" << endl;
}

// 图形变换测试
void transformTest1() {
	createEnv();

	vector<POINT> p = {
		{-100, -100}, {50, -50}, {100, 100}, {-50, 50}
	};
	//m_fillcrectangle(0, 0, 100, 50, BLACK, RED);
	m_polygon(p);
	m_polygon(ZEigen::TransformPoints(ZEigen::Scale3f(2, 2), p), GREEN);
	m_polygon(ZEigen::TransformPoints(ZEigen::Rotate3f(15), p), RED);
	//m_polygon(ZEigen::TransformPoints(ZEigen::Translation3f(50, 50), p), BLUE);
	//m_polygon(ZEigen::TransformPoints({ ZEigen::Translation3f(50, 50), ZEigen::Rotate3f()}, p), YELLOW);
	
	int key = _getch();
	closegraph();
}

void transformTest2() {
	createEnv();

	vector<POINT> triangle = {
		{50, 50}, {100, 50}, {50, 100}
	};

	m_polygon(triangle);
	m_polygon(ZEigen::TransformPoints({ ZEigen::Rotate3f(45, 50, 50) }, triangle), GREEN);
	
	// 对称矩阵测试
	m_polygon(ZEigen::TransformPoints({ ZEigen::Symmetry3f({0, 0}, {50, 50}) }, triangle), BLUE);
	
	int key = _getch();
	closegraph();
}
